﻿using Commands;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PluginSendToKindle
{
    class SendToKindle
    {
        public SendToKindle(string kindleMail, IMailer mailer, IKindlePluginSettings settings)
        {
            this._kindleMail = kindleMail;
            this._mailer = mailer;
            _settings = settings;
        }

        internal void Send(string folderWithSavedAttaches)
        {
            var dirInfo = new DirectoryInfo(folderWithSavedAttaches);

            var goodFileNames = new List<FileInfo>();

            Parallel.ForEach(dirInfo.GetFiles(), file =>
                {
                    if (_NeedConversion(file))
                    {
                        var converted = _Convert(file);
                        goodFileNames.Add(converted);
                    }
                    else
                        goodFileNames.Add(file);
                }
            );

            // Send good files to kindle. Split them to packs which are in Amazon limits.
            _SendFiles(goodFileNames);
        }

        private void _SendFiles(List<FileInfo> goodFileNames)
        {
            var i = 0;
            long totalSize = 0;
            var currentFiles = new List<string>();

            while (i < goodFileNames.Count)
            {
                while (totalSize < MAX_SIZE && currentFiles.Count < MAX_FILECOUNT && i < goodFileNames.Count)
                {
                    if (goodFileNames[i] != null)
                    {
                        currentFiles.Add(goodFileNames[i].FullName);
                        totalSize += goodFileNames[i].Length;
                    }

                    i++;
                }

                var mailAddress = _GetMail(_kindleMail);
                _mailer.SendMail(mailAddress, string.Empty, currentFiles, string.Empty);
                totalSize = 0;
                currentFiles.Clear();
            }
        }

        private string _GetMail(string kindleMail)
        {
            if (string.IsNullOrEmpty(kindleMail))
                return _settings.GetDefaultKindleMail();

            // If mail is real mail address.s
            if (kindleMail.Contains("@"))
                return kindleMail;

            if (_settings.Kindles.Any(x => x.Name == kindleMail))
                return _settings.Kindles.First(x => x.Name == kindleMail).Address;

            return _settings.GetDefaultKindleMail();
        }

        private FileInfo _Convert(FileInfo file)
        {
            var format = file.Extension;

            if (format == FB2_FORMAT)
            {
                var newFileName=file.FullName.Replace(FB2_FORMAT, MOBI_FORMAT);

                // Call external converter and wait while it will exit.
                var process = Process.Start(_settings.Fb2Kf8ConverterPath, _FormatArguments( file.FullName, newFileName) );
                process.WaitForExit();

                return new FileInfo(newFileName);
            }
            else
            {
                // We don't support this format.
                return null;
            }
        }

        private string _FormatArguments(string fileName, string newFileName)
        {
            return string.Format("\"{0}\" \"{1}\"", fileName, newFileName);
        }

        private bool _NeedConversion(FileInfo file)
        {
            return !ALLOWED_EXTENSIONS.Contains(file.Extension.ToUpper());
        }

        #region Private members

        private IMailer _mailer;
        private string _kindleMail;

        // Amazon's SendToKindle service restrictions.
        private readonly static string[] ALLOWED_EXTENSIONS = new string[] {".DOC", ".DOCX", ".HTML", ".HTM", ".RTF",
            ".JPEG", ".JPG", ".MOBI", ".AZW", "GIF", "PNG", "BMP", "PDF"};
        private const int MAX_SIZE = 50 * 1024 * 1024;
        private const int MAX_FILECOUNT = 25;

        private string FB2_FORMAT = ".fb2";
        private string MOBI_FORMAT = ".mobi";
        private IKindlePluginSettings _settings;

        #endregion
    }
}
